package cn.iocoder.yudao.module.lowcode.controller.admin.datasource;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.lowcode.controller.admin.datasource.vo.*;
import cn.iocoder.yudao.module.lowcode.dal.dataobject.datasource.LowcodeDataSourceConfigDO;
import cn.iocoder.yudao.module.lowcode.service.datasource.LowcodeDataSourceConfigService;
import cn.iocoder.yudao.module.lowcode.service.generic.GenericTableServiceEnhancer;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "低代码 - 数据源配置")
@RestController
@RequestMapping("/lowcode/data-source-config")
@Validated
@Slf4j
public class LowcodeDataSourceConfigController {

    @Resource
    private LowcodeDataSourceConfigService dataSourceConfigService;

    @Resource
    private GenericTableServiceEnhancer tableServiceEnhancer;

    @PostMapping("/create")
    @Operation(summary = "创建数据源配置")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:create')")
    public CommonResult<Long> createDataSourceConfig(@Valid @RequestBody LowcodeDataSourceConfigSaveReqVO createReqVO) {
        return success(dataSourceConfigService.createDataSourceConfig(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新数据源配置")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:update')")
    public CommonResult<Boolean> updateDataSourceConfig(@Valid @RequestBody LowcodeDataSourceConfigSaveReqVO updateReqVO) {
        dataSourceConfigService.updateDataSourceConfig(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除数据源配置")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:delete')")
    public CommonResult<Boolean> deleteDataSourceConfig(@RequestParam("id") Long id) {
        dataSourceConfigService.deleteDataSourceConfig(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得数据源配置")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:query')")
    public CommonResult<LowcodeDataSourceConfigRespVO> getDataSourceConfig(@RequestParam("id") Long id) {
        LowcodeDataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id);
        return success(BeanUtils.toBean(dataSourceConfig, LowcodeDataSourceConfigRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得数据源配置分页")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:query')")
    public CommonResult<PageResult<LowcodeDataSourceConfigRespVO>> getDataSourceConfigPage(@Valid LowcodeDataSourceConfigPageReqVO pageReqVO) {
        PageResult<LowcodeDataSourceConfigDO> pageResult = dataSourceConfigService.getDataSourceConfigPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, LowcodeDataSourceConfigRespVO.class));
    }

    @GetMapping("/list-enabled")
    @Operation(summary = "获得启用的数据源配置列表")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:query')")
    public CommonResult<List<LowcodeDataSourceConfigRespVO>> getEnabledDataSourceConfigList() {
        List<LowcodeDataSourceConfigDO> list = dataSourceConfigService.getEnabledDataSourceConfigList();
        return success(BeanUtils.toBean(list, LowcodeDataSourceConfigRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出数据源配置 Excel")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:export')")
    public void exportDataSourceConfigExcel(@Valid LowcodeDataSourceConfigPageReqVO pageReqVO,
                                             HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<LowcodeDataSourceConfigDO> list = dataSourceConfigService.getDataSourceConfigPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "数据源配置.xls", "数据", LowcodeDataSourceConfigRespVO.class,
                BeanUtils.toBean(list, LowcodeDataSourceConfigRespVO.class));
    }

    @GetMapping("/test")
    @Operation(summary = "测试接口是否可用")
    public CommonResult<String> test() {
        return success("LowcodeDataSourceConfigController is working!");
    }

    @GetMapping("/tables-no-auth")
    @Operation(summary = "获取数据源的表列表（无权限验证）")
    public CommonResult<List<String>> getTableListNoAuth(@RequestParam("id") Long id,
                                                          @RequestParam(value = "tableName", required = false) String tableName) {
        return success(dataSourceConfigService.getTableList(id, tableName));
    }

    @GetMapping("/tables")
    @Operation(summary = "获取数据源的表列表")
    @Parameter(name = "id", description = "数据源配置ID", required = true)
    @Parameter(name = "tableName", description = "表名模糊匹配")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:query')")
    public CommonResult<List<LowcodeTableInfoRespVO>> getTableList(@RequestParam("id") Long id,
                                                    @RequestParam(value = "tableName", required = false) String tableName) {
        return success(dataSourceConfigService.getTableInfoList(id, tableName));
    }

    @GetMapping("/table/columns")
    @Operation(summary = "获取表的字段信息")
    @Parameter(name = "id", description = "数据源配置ID", required = true)
    @Parameter(name = "tableName", description = "表名", required = true)
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:query')")
    public CommonResult<List<LowcodeDataSourceConfigService.TableColumnInfo>> getTableColumnList(
            @RequestParam("id") Long id,
            @RequestParam("tableName") String tableName) {
        return success(dataSourceConfigService.getTableColumnList(id, tableName));
    }

    @GetMapping("/supported-types")
    @Operation(summary = "获取支持的数据库类型")
    public CommonResult<List<String>> getSupportedDatabaseTypes() {
        return success(dataSourceConfigService.getSupportedDatabaseTypes());
    }

    @PostMapping("/test-connection")
    @Operation(summary = "测试数据源连接")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:query')")
    public CommonResult<LowcodeDataSourceTestRespVO> testConnection(@Valid @RequestBody LowcodeDataSourceTestReqVO testReqVO) {
        return success(dataSourceConfigService.testConnection(testReqVO));
    }

    @PostMapping("/import-table")
    @Operation(summary = "导入单个表并生成 Magic API 接口")
    @Parameter(name = "dataSourceId", description = "数据源ID", required = true)
    @Parameter(name = "tableName", description = "表名", required = true)
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:import')")
    public CommonResult<Boolean> importTable(@RequestParam("dataSourceId") Long dataSourceId,
                                              @RequestParam("tableName") String tableName) {
        log.info("=== [importTable] 开始导入表 ===");
        log.info("[importTable] 接收请求参数: dataSourceId={}, tableName={}", dataSourceId, tableName);
        try {
            // 1. 获取表信息（验证表是否存在）
            List<LowcodeTableInfoRespVO> tables = dataSourceConfigService.getTableInfoList(dataSourceId, tableName);
            if (tables.isEmpty()) {
                return CommonResult.error(400, "表不存在: " + tableName);
            }
            
            LowcodeTableInfoRespVO table = tables.get(0);
            
            // 2. Magic API 接口生成已改为在代码生成器的表配置更新时触发
            log.info("[importTable] 表导入成功，Magic API 接口将在代码生成器配置更新时自动生成: table={}", table.getName());
            
            return success(true);
            
        } catch (Exception e) {
            return CommonResult.error(500, "导入表失败: " + e.getMessage());
        }
    }

    @PostMapping("/import-tables-batch")
    @Operation(summary = "批量导入表并生成 Magic API 接口")
    @PreAuthorize("@ss.hasPermission('lowcode:data-source-config:import')")
    public CommonResult<ImportTablesResult> importTablesBatch(@Valid @RequestBody ImportTablesRequest request) {
        try {
            int totalCount = request.getTableNames().size();
            int successCount = 0;
            int errorCount = 0;
            
            for (String tableName : request.getTableNames()) {
                try {
                    // 1. 获取表信息
                    List<LowcodeTableInfoRespVO> tables = dataSourceConfigService.getTableInfoList(request.getDataSourceId(), tableName);
                    if (tables.isEmpty()) {
                        errorCount++;
                        continue;
                    }
                    
                    LowcodeTableInfoRespVO table = tables.get(0);
                    
                    // 2. 触发 Magic API 接口生成
                    tableServiceEnhancer.notifyTableCreated(
                        table.getName(),
                        request.getDataSourceId(),
                        table.getComment()
                    );
                    
                    successCount++;
                    
                } catch (Exception e) {
                    errorCount++;
                }
            }
            
            ImportTablesResult result = new ImportTablesResult();
            result.setTotalCount(totalCount);
            result.setSuccessCount(successCount);
            result.setErrorCount(errorCount);
            result.setMessage(String.format("总计 %d 个表，成功 %d 个，失败 %d 个", totalCount, successCount, errorCount));
            
            return success(result);
            
        } catch (Exception e) {
            return CommonResult.error(500, "批量导入失败: " + e.getMessage());
        }
    }


}